package com.wyl.template.aop;

import com.alibaba.fastjson.JSON;
import com.wyl.template.aop.annotation.SysLogger;
import com.wyl.template.constant.AppConstants;
import com.wyl.template.domain.model.SysLogDO;
import com.wyl.template.domain.model.SysUserDO;
import com.wyl.template.enums.LoggerType;
import com.wyl.template.mapper.SysLogMapper;
import com.wyl.template.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;

/**
 * @Auther: wyl
 * @Date: 2021/7/1
 * @Description:
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

    @Autowired
    private SysLogMapper logMapper;

    @Pointcut("@annotation(com.wyl.template.aop.annotation.SysLogger)")
    private void cutPoint() {
    }

    //"@annotation(com.wyl.template.aop.annotation.SysLogger)"
    @AfterReturning(pointcut = "cutPoint()", returning = "result")
    public void arround(JoinPoint joinPoint, Object result) {

        SysLogger classLogger = joinPoint.getTarget().getClass().getAnnotation(SysLogger.class);
        SysLogger methodLogger = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(SysLogger.class);

        if (classLogger == null || methodLogger == null) {
            return;
        }

        //参数对象
        Object[] args = joinPoint.getArgs();
        /*获取日志内容*/
        String content = "【" + classLogger.group() + "】" + methodLogger.name();
        /*获取日志类型*/
        LoggerType type = methodLogger.type();

        /*获取request参数*/
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String traceId = MDC.get(AppConstants.TRACE_ID);

        Subject subject = SecurityUtils.getSubject();
        SysUserDO currentUser = (SysUserDO) subject.getPrincipal();

        // 赋值
        SysLogDO sysLog = new SysLogDO();

        sysLog.setTraceId(Long.valueOf(traceId));
        sysLog.setUserId(currentUser.getId());
        sysLog.setUserName(currentUser.getUserName());
        sysLog.setIp(CommonUtil.getIpAddr(request));

        sysLog.setUrl(request.getRequestURI());
        sysLog.setMethod(request.getMethod());
        sysLog.setRequestType(type.getDesc());
        sysLog.setContent(content);
        sysLog.setParams(Arrays.toString(args));
        sysLog.setResult(JSON.toJSONString(result));
        String resultT = JSON.toJSONString(result);
        if(resultT.length()>2000){
            resultT = resultT.substring(0,2000);
        }
        sysLog.setResult(resultT);

        sysLog.setCreateTime(new Date());
        sysLog.setUpdateTime(new Date());
        try {
            logMapper.insert(sysLog);
        }catch (Exception e){
            log.error("记录操作日志到数据库失败,{}",e.getMessage());
        }
    }
}
